package com.insa.flopenshop;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.TreeSet;

/**
 * Modélise une instance du problème open shop
 * 
 * @author Luc DUZAN
 * 
 */
public class Instance {
	/**
	 * Ex : nombre de produit à fabriquer
	 */
	private final int numTache;

	public static final File INSTANCE_DIR = new File("hard-os");

	/**
	 * Ex : nombre de machine différentes nécessaires pour la pièce
	 */
	private final int numRessourceDedie;

	/**
	 * Ex : nombre de ligne de chaîne d'assemblage
	 */
	private final int numRessouceUniversel;

	/**
	 * Matrice qui indique le temps nécessaire pour chaque tâche sur chaque
	 * machine les lignes représentent les tâches de 0 à numTache et les
	 * colonnes représentent les machines de 0 à numMachine
	 * 
	 * [numTache][numRessourceDedie]
	 */
	private final int[][] tempsMachinesTaches;

	private final File file;
	/**
	 * Retourne toute les instances du contenu INSTANCE_DIR en parsant les
	 * fichiers dont le nom commence par GP
	 * 
	 * @return
	 * @throws FileNotFoundException
	 */
	public static List<Instance> getAllInstances() throws FileNotFoundException {
		List<Instance> result = new LinkedList<>();
		Instance si;
		for (File f : Instance.INSTANCE_DIR.listFiles()) {
			if (f.getName().indexOf("GP") == 0) {
				si = new Instance(f);
				result.add(si);
			}
		}
		return result;
	}

	public Instance(File file) throws FileNotFoundException {
		Scanner sc = new Scanner(file);
		sc.nextLine();
		this.numTache = sc.nextInt();
		this.numRessourceDedie = sc.nextInt();
		this.numRessouceUniversel = 2;
		this.tempsMachinesTaches = new int[numTache][numRessourceDedie];
		this.file = file;
		for (int nt = 0; nt < numTache; nt++) {
			for (int nrd = 0; nrd < numRessourceDedie; nrd++) {
				tempsMachinesTaches[nt][nrd] = sc.nextInt();
			}
		}
		sc.close();
	}

	/**
	 * Renvoie le nombre de tâche
	 * 
	 * @return
	 */
	public int getNumTache() {
		return numTache;
	}

	/**
	 * 
	 * @param tache
	 *            : 0 <= tache < numTache
	 * @param ressourceDedie
	 *            : 0 <= ressourceDedie < numRessourceDedie
	 * @return le temps nécéssaire à la tache sur la ressource dédiée
	 */
	public int getTime(int tache, int ressourceDedie) {
		if(tache == -1 || ressourceDedie == -1) {
			return 0;
		}
		
		return tempsMachinesTaches[tache][ressourceDedie];
	}

	public int getTime(SousTache sousTache) {
		return getTime(sousTache.getTache(), sousTache.getRessourceDedie());
	}

	/**
	 * Renvoie le nombre de ressource dédié
	 * 
	 * @return
	 */
	public int getNumRessourceDedie() {
		return numRessourceDedie;
	}

	/**
	 * Renvoie le nombre de ressource universelle
	 * 
	 * @return
	 */
	public int getNumRessouceUniversel() {
		return numRessouceUniversel;
	}

	/**
	 * Retourne toute les sous tâches compatibles avec la sous tâche
	 * correspondante à (tache, ressourceDedie)
	 * 
	 * @param tache
	 *            le numéro de la tâche de la sous tâche
	 * @param ressourceDedie
	 *            numéro de la machine correspondant à notre sous tâche
	 * @return
	 */
	public TreeSet<SousTache> getCompatibleSousTache(int tache,
			int ressourceDedie) {
		TreeSet<SousTache> result = new TreeSet<SousTache>();

		for (int nt = 0; nt < numTache; nt++) {
			if (nt != tache) {
				for (int nrd = 0; nrd < numRessourceDedie; nrd++) {
					if (nrd != ressourceDedie) {
						result.add(new SousTache(this, nt, nrd));
					}
				}
			}
		}

		return result;
	}

	public TreeSet<SousTache> getAllSousTache() {
		TreeSet<SousTache> result = new TreeSet<>();
		for (int nt = 0; nt < numTache; nt++) {
			for (int nrd = 0; nrd < numRessourceDedie; nrd++) {
				result.add(new SousTache(this, nt, nrd));
			}
		}
		
		return result;
	}

	/**
	 * Retourne toute les sous tâches compatibles avec la sous tâche
	 * 
	 * @param sousTache
	 * @return
	 */
	public TreeSet<SousTache> getCompatibleSousTache(SousTache sousTache) {
		return getCompatibleSousTache(sousTache.getTache(),
				sousTache.getRessourceDedie());
	}

	public int getNumSousTache() {
		return numRessourceDedie*numTache;
	}

	public String getFileName() {
		return file.getName();
	}
	
	@Override
	public String toString() {
		String ret = "";
		ret += "Instance {";
		ret += "\nFichier : " + file.getName();
		ret += "\nNombre de ressources dediees : " + numRessourceDedie;
		ret += "\nNombre de ressources universelles : " + numRessouceUniversel;
		for(int i = 0 ; i < getNumTache() ; i++){
			ret += "\n[";
			for(int j = 0 ; j < getNumRessourceDedie() ; j++){
				if(j != 0)
					ret += ", ";
				ret += tempsMachinesTaches[i][j];
			}
			ret += "]";
		}
		ret += "\n}";
		
		return ret;
	}

}
